package com.xiyang.operater.config.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 *
 * SecurityContextPersistenceFilter
 * {@link org.springframework.security.web.context.SecurityContextPersistenceFilter}
 * 该类在所有的filter之前，是从{@link org.springframework.security.web.context.SecurityContextRepository}取出用户认证信息，
 * 默认实现类@{@link org.springframework.security.web.context.HttpSessionSecurityContextRepository},
 * 其会从Session中取出已认证用户的信息，提高效率，避免每一次请求都要查询用户认证信息。
 * 取出之后会放入{@link org.springframework.security.core.context.SecurityContextHolder}中，以便其他filter使用，
 * SecurityContextHolder使用ThreadLocal存储用户认证信息，保证了线程之间的信息隔离，最后再finally中清楚该信息
 *                                      ⇩
 *
 * @author xiyang.ycj
 * @since Jun 25, 2019 01:52:43 AM
 */
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    private final LoginSuccessHandler loginSuccessHandler;

    private final LoginFailureHandler loginFailureHandler;

    private final LoginAuthenticationProvider loginAuthenticationProvider ;

    private final CustomUserDetailsService userDetailsService ;

    @Autowired
    public WebSecurityConfig(LoginSuccessHandler loginSuccessHandler, LoginFailureHandler loginFailureHandler, LoginAuthenticationProvider loginAuthenticationProvider, CustomUserDetailsService userDetailsService) {
        this.loginSuccessHandler = loginSuccessHandler;
        this.loginFailureHandler = loginFailureHandler;
        this.loginAuthenticationProvider = loginAuthenticationProvider;
        this.userDetailsService = userDetailsService;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        //指定密码加密所使用的加密器为passwordEncoder()
        //需要将密码加密后写入数据库
      // auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        auth.authenticationProvider(loginAuthenticationProvider).userDetailsService(userDetailsService); // 自定义provider
        auth.eraseCredentials(false); // 不删除凭证，以便记住用户
    }

    /*   configureGlobal可以跨多个WebSecurityConfigurerAdapter
         configure只能只能作用一个     */

    /*@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }*/

    /**
     * Override this method to configure {@link WebSecurity}. For example, if you wish to
     * ignore certain requests.
     *
     * @param web
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // 添加拦截器
                //.addFilterBefore(customFilterSecurityInterceptor, FilterSecurityInterceptor.class)
                .authorizeRequests()
                //其他所有资源都需要认证，登陆后访问
               // .antMatchers("/123").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()

                //指定登录页是”/login”
                .loginPage("/login")
                .permitAll()
                //登录成功后可使用loginSuccessHandler()存储用户信息，可选。
                // 指定要使用的指定要使用的AuthenticationSucessHandler。
                // 默认值为savedRequestAwardeAuthenticationSuccessHandler，未设置其他属性。
                .successHandler(loginSuccessHandler)
                .failureHandler(loginFailureHandler)
                .and()
                .logout()
                //退出登录后的默认网址是”/home”,这个页面不需要登录也可以访问
                //.logoutSuccessUrl("/home")
                .permitAll()
                 // HttpSession 失效
                .invalidateHttpSession(true)
                .and()
                //登录后记住用户，下次自动登录,数据库中必须存在名为persistent_logins的表
                .rememberMe()
                // 有效时间
                .tokenValiditySeconds(1209600);
       // http.authenticationProvider(loginAuthenticationProvider);
    }
}
